
#include "ParameterInfo.h"
#include "Common/Structures.h"
#include "Common/Strings.h"
#include "Runtime.Low/Utils.h"
#include "../CastingRoutines.h"

using namespace ttg_internal::utils;
using namespace ttg_internal::structures;

//---------------------
//--- ParameterInfo ---
//---------------------

ParameterType ParameterInfo::determineType(System::String ^type)
{
	switch (TypeSerializer::deserializeType(CastingRoutines::castString(type).c_str()))
	{
		case TypeSerializer::Bool:
			return ParameterType::Bool;

		case TypeSerializer::Int64:
			return ParameterType::Int64;

		case TypeSerializer::Double:
			return ParameterType::Double;

		case TypeSerializer::String:
			return ParameterType::String;

		case TypeSerializer::Enum:
			return ParameterType::Enum;

		case TypeSerializer::Void:
		default:
			return ParameterType::Void;
	}
}

//--------------------------
//--- ParameterInfo_Bool ---
//--------------------------

bool ParameterInfo_Bool::CanBeAssigned(System::String ^value)
{
	return value == "true" || value == "false";
}

//--------------------------
//--- ParameterInfo_Enum ---
//--------------------------

ParameterInfo_Enum::ParameterInfo_Enum(System::String ^type)
	:ParameterInfo(ParameterType::Enum)
{
	std::vector<std::string> elements
		= TypeSerializer::deserializeEnumElements(CastingRoutines::castString(type).c_str());
	_elements = gcnew array<System::String ^>(elements.size());
	for (size_t i = 0; i < elements.size(); i++)
		_elements[i] = gcnew System::String(elements[i].c_str());
}

bool ParameterInfo_Enum::CanBeAssigned(System::String ^value)
{
	for each (System::String ^e in Elements)
		if (e == value)
			return true;
	return false;
}

//---------------------------
//--- ParameterInfo_Int64 ---
//---------------------------

ParameterInfo_Int64::ParameterInfo_Int64(System::String ^type)
	:ParameterInfo(ParameterType::Int64)
{
	ttg::math::int64 lo, hi;
	_hasBounds
		= TypeSerializer::deserializeInt64Bounds(CastingRoutines::castString(type).c_str(), lo, hi);
	if (_hasBounds)
	{
		_lo = lo;				//Stupid Visual C++!
		_hi = hi;
	}
	else
	{
		_lo = System::Int64::MinValue;
		_hi = System::Int64::MaxValue;
	}
}

bool ParameterInfo_Int64::CanBeAssigned(System::String ^value)
{
	__int64 tmp;
	if (System::Int64::TryParse(value, tmp))
		return HasBounds ? (LowBound <= tmp && tmp <= HighBound) : true;
	else
		return false;
}

//----------------------------
//--- ParameterInfo_Double ---
//----------------------------

ParameterInfo_Double::ParameterInfo_Double(System::String ^type)
	:ParameterInfo(ParameterType::Double)
{
	double lo, hi;
	_hasBounds
		= TypeSerializer::deserializeDoubleBounds(CastingRoutines::castString(type).c_str(), lo, hi);
	if (_hasBounds)
	{
		_lo = lo;				//Stupid Visual C++!
		_hi = hi;
	}
	else
	{
		_lo = System::Double::MinValue;
		_hi = System::Double::MaxValue;
	}
}

bool ParameterInfo_Double::CanBeAssigned(System::String ^value)
{
	double tmp;
	value = value->Replace(',', '.');
	if (ttg::strings::isFloat(CastingRoutines::castString(value), tmp))
	{
		return HasBounds ? (LowBound <= tmp && tmp <= HighBound) : true;
	}
	else
		return false;
}
